<?php
/**
 * 2023-10-14
 * 此安装方法已弃用，请使用/install 页面安装
 * 创建数据库以及配置数据库文件
 * 命名：
 * php webman config:mysql --h 127.0.0.1 --port 3306 --u root --p 123456 --d databasename --in 0
 * 说明：
 * --h host地址（允许省略不写（默认值：127.0.0.1），如果写，必须带值）
 * --port 端口号（允许省略不写（默认值：3306），如果写，必须带值）
 * --u 数据库用户名（必填）
 * --p 数据库密码（必填）
 * --d 数据库名（必填）
 * --in 是否强制写入数据库名（允许为空，默认值：0），1=强制写入；0=不强制（如果存在表，将安装失败）
 */

namespace app\command;

use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
use PDO;
use ZipStream\Exception;

class ConfigMySQLCommand extends Command
{

    protected $pdo;

    protected $databaseName;

    protected static $defaultName = 'config:mysql';

    protected static $defaultDescription = '显示当前MySQL服务器配置';

    protected function configure()
    {
        $this
            ->addOption('h', null, InputOption::VALUE_OPTIONAL, 'host', '127.0.0.1')
            ->addOption('port', null, InputOption::VALUE_OPTIONAL, 'port', '3306')
            ->addOption('u', null, InputOption::VALUE_REQUIRED, '数据库用户名')
            ->addOption('p', null, InputOption::VALUE_REQUIRED, '数据库密码')
            ->addOption('d', null, InputOption::VALUE_REQUIRED, '数据库名')
            ->addOption('in', null, InputOption::VALUE_OPTIONAL, '是否强制写入数据库名', '0');
    }

    protected function execute(InputInterface $input, OutputInterface $output)
    {
        $host     = $input->getOption('h');
        $hostport = $input->getOption('port');
        $userName = $input->getOption('u');
        $password = $input->getOption('p');
        $in       = $input->getOption('in');

        $this->databaseName = $input->getOption('d');

        if (empty($host)) {
            $output->writeln("host地址不能为空");

            return self::FAILURE;
        }
        if (empty($userName)) {
            $output->writeln("数据库用户名不能为空");

            return self::FAILURE;
        }
        if (empty($password)) {
            $output->writeln("数据库密码不能为空");

            return self::FAILURE;
        }
        if (empty($this->databaseName)) {
            $output->writeln("数据库名不能为空");

            return self::FAILURE;
        }

        //判断数据库是否连接成功
        try {
            $this->pdo = new PDO("mysql:host={$host};port={$hostport}", $userName, $password, array(
                PDO::ATTR_ERRMODE            => PDO::ERRMODE_EXCEPTION,
                PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES utf8"
            ));
        } catch (\Exception $e) {
            $output->writeln("数据库连接失败");

            return self::FAILURE;
        }

        $resDbExist = $this->isDBExist();
        if ($resDbExist && $in == 0) {
            $output->writeln(PHP_EOL);
            $output->writeln("该数据库已存在，如需强制覆盖安装请在命令后面添加： --in 1，例如：".PHP_EOL);
            $output->writeln("php webman config:mysql --u $userName --p $password --d $this->databaseName --in 1");
            $output->writeln(PHP_EOL);

            return self::FAILURE;
        }

        //检测mysql版本是否符合要求（最低需要5.5版本）
        $res    = $this->pdo->query("select VERSION()");
        $result = $res->fetch();
        if ($result[0] < 5.5) {
            $output->writeln("本系统需要数据库版本最低为5.5，当前数据库版本为".$result[0]);

            return self::FAILURE;
        }

        if ($this->getInstallSql() == false) {
            $output->writeln("无法读取根目录下install.sql文件，请检查是否有读权限");

            return self::FAILURE;
        }

        $output->writeln('正在安装数据库，请稍候...');

        $this->pdo->query("CREATE DATABASE IF NOT EXISTS `{$this->databaseName}` CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;");

        $output->writeln('创建数据库【'.$this->databaseName.'】成功。');
        $output->writeln('正在写入数据表，请稍候...');

        $this->pdo->query("USE `{$this->databaseName}`");
        $this->pdo->exec($this->getInstallSql());
        $output->writeln('写入表成功。');
        $output->writeln('正在创建.env文件，请稍候...');

        $config             = [];
        $config['hostname'] = $host;
        $config['database'] = $this->databaseName;
        $config['username'] = $userName;
        $config['password'] = $password;
        $config['hostport'] = $hostport;
        $config['prefix']   = 'cmf_';

        $EnvFile = base_path().DIRECTORY_SEPARATOR.".env";

        try {
            @file_put_contents($EnvFile, $this->writeEnv($config));
            $output->writeln('写入env文件成功。');
            $output->writeln(PHP_EOL);
            $output->writeln('安装完成。使用启动命令愉快的访问系统吧~~~');
            $output->writeln(PHP_EOL);
            $output->writeln("后台地址：");
            $output->writeln("http://127.0.0.1:8787/admin");
            $output->writeln(PHP_EOL);

        } catch (Exception $e) {
            $output->writeln('Error:'.PHP_EOL);
            $output->writeln('无法写入数据库信息到.env文件，请检查是否有写权限。或者自行配置.env文件信息');

            return self::FAILURE;
        }

        return self::SUCCESS;
    }

    /**
     * 写入 .env文件
     */
    private function writeEnv($data)
    {
        $hostname = $data['hostname'];
        $database = $data['database'];
        $username = $data['username'];
        $password = $data['password'];
        $hostport = $data['hostport'];
        $prefix   = $data['prefix'];

        $config = <<<EOT
[APP]
APP_DEBUG = true
APP_PORT = 8787

[SQL]
DB_DEFAULT = mysql
HOSTNAME = $hostname
DATABASE = $database
DBNAME = $username
DBPASS = $password
HOSTPOINT = $hostport
PREFIX = $prefix

[REDIS]
HOST = 127.0.0.1
PORT = 6379
PASSWORD =
DATABASE = 8
PREFIX = huicmf_redis_

[HUICMF]
#允许登录失败几次
login_failure_times = 10

#登录失败超过N次则后，多久允许重写登录（分钟）
login_failure_min = 10

#是否为演示环境
IS_DEMO = false

EOT;

        return $config;

    }

    /**
     * 获取安装的sql语句
     * @return void
     */
    private function getInstallSql()
    {
        $rootDir = base_path().DIRECTORY_SEPARATOR;
        $sql     = @file_get_contents($rootDir.'install.sql');
        if ( ! $sql) {
            return false;
        }

        return $sql;
    }

    /**
     * 查询数据库表是否存在
     * @return void
     */
    private function isDBExist()
    {
        $sql           = "show databases;";
        $res           = $this->pdo->query($sql);
        $res           = $res->fetchAll(PDO::FETCH_ASSOC);
        $database_list = [];
        foreach ($res as $k => $v) {
            $database_list[] = $v['Database'];
        }
        if (in_array($this->databaseName, $database_list)) {
            return true;
        } else {
            return false;
        }
    }

    // 判断文件或目录是否有写的权限
    function is_really_writable($file)
    {
        if (DIRECTORY_SEPARATOR == '/' and @ ini_get("safe_mode") == false) {
            return is_writable($file);
        }
        if ( ! is_file($file) or ($fp = @fopen($file, "r+")) === false) {
            return false;
        }

        fclose($fp);

        return true;
    }
}
